import React, { Component } from 'react';
import moment from 'moment';
import {
  AudioFilled,
  AudioOutlined,
  CustomerServiceOutlined,
  PhoneOutlined,
  SoundOutlined,
  VerticalAlignBottomOutlined,
} from '@ant-design/icons';
import { Button, Empty, Space } from 'antd';
import { WAudio } from 'components/UILibrary/wAudio';
import { ChatMessage, ChatProp, ChatState } from 'seats/schema/ChatSeat';
import { closeListenCall, getDialogue, interceptCall, openListenCall } from 'seats/servers/servers';

import CallTime from 'seats/components/CallTime';
import { getSysSip } from 'servers/sip';
import eventBus from 'utils/eventBus';
import { filterDialogue, webDebug } from 'utils/tools';
import { connect } from 'react-redux';
import { JSONObject } from 'seats/schema/common';
import { setManListenCallId } from 'store/root/action';

import './style.scss';

/**
 *坐席端-示闲工作台-聊天记录-模块
 *应用类组件：基于原来chat组件开发
 *组件特点：头部-通话时长；底部按钮：人工介入，人工监听
 */
class ChatSeat extends Component<ChatProp, ChatState> {
  /**
   * 接收方头像
   */
  private calledImg: string;

  /**
   * 发送方头像
   */
  private callerImg: string;
  /**
   * 当前页面播放对象
   */
  private musicAudio: HTMLAudioElement;

  /**
   * 会话内容容器
   */
  private bodyRef: React.RefObject<HTMLDivElement>;
  /**
   * 音频播放容器
   */
  private audioRef: React.RefObject<any>;
  /**存储接听等待时长 */
  private waitTimeRef: React.RefObject<any>;
  /**存储接听等待时长-计时器 */
  private timer: any;
  constructor(prop: ChatProp) {
    super(prop);
    this.musicAudio = new Audio();
    this.calledImg = '/webseats/clientAva.jpeg';
    this.callerImg = '/webseats/logo192.png';
    this.bodyRef = React.createRef();
    this.audioRef = React.createRef();
    this.waitTimeRef = React.createRef();
    this.timer = React.createRef();
    this.state = {
      chatType: prop.chatType || '',
      showHistoryLink: !!prop.showHistoryLink,
      callRecordId: prop.callRecordId,
      messages: prop.messages || [],
      showDownload: prop.showDownload == null ? false : prop.showDownload,
      showStatusHeader: prop.showStatusHeader == null ? true : prop.showStatusHeader,
      callSerialNumber: prop.callSerialNumber || '',
      talkRecord: prop.talkRecord,
      centerCallId: prop.centerCallId || '',
      showHeadBar: !!prop.showHeadBar,
      phoneNum: void 0,
      status: prop.status,
      callTime: prop.callTime,
      inCall: false, // 当前弹屏是否人工监听中,false否
      playings: [],
      isTransferShow: false, // 是否转人工组件触发
    };
    this.handleContactMan = this.handleContactMan.bind(this);
    this.handleInterceptCall = this.handleInterceptCall.bind(this);
    this.handleOpenManListenCall = this.handleOpenManListenCall.bind(this);
    this.handleCloseManListenCall = this.handleCloseManListenCall.bind(this);
  }

  /**转人工-接听提示-显示 */
  public showTransferPop() {
    const { centerCallId } = this.state;
    console.log('showTransferPop===展示【接听】按钮', centerCallId);
    this.setState({
      isTransferShow: true,
    });
    (this.waitTimeRef as any).current = 1;
    this.timer = setInterval(() => {
      (this.waitTimeRef as any).current++;
    }, 1000);
  }

  /**转人工-接听提示-隐藏 */
  public hideTransferPop() {
    const { centerCallId } = this.state;
    console.log('hideTransferPop===隐藏【接听】按钮**', centerCallId);
    this.setState({
      isTransferShow: false,
    });
    (this.waitTimeRef as any).current = 0;
    clearInterval(this.timer);
  }

  /**挂断监听 */
  public closeManListen() {
    // 取消监听样式
    this.setState({
      inCall: false,
    });
    // 挂断监听
    this.stopListen();
  }

  /**
   * 设置会话记录
   */
  public setRecord(message: ChatMessage[]): void {
    this.setState(
      {
        messages: message,
      },
      () => {
        this.scrollToBottom();
      }
    );
  }

  /**
   * 得到当前会话的通话号码
   */
  public getPhone(): string {
    return this.state.phoneNum || '';
  }
  /**
   * 得到当前会话的呼叫中心Id
   */
  public getCenterCallId(): string {
    return this.state.centerCallId || '';
  }

  /**
   * 得到当前会话的Id
   */
  public getCallRecordId(): string {
    return this.state.callRecordId || '';
  }

  /**
   * 播放音频-单句
   */
  private playSound(item: ChatMessage, index: number): void {
    console.log(item, '播放音频');
    // 顶部播放暂停
    this.audioRef.current && this.audioRef.current.pauseAudio();
    // 其他单句暂停
    this.musicAudio.pause();
    const arr = [];
    arr[index] = true;
    this.setState({
      playings: arr,
    });
    // 单句-切换播放
    this.musicAudio.src = (process.env.REACT_APP_API_URL || '') + item.sound;
    this.musicAudio.play().catch((error: any) => {
      // 当播放异常时，走异常流程
      console.log(error);
    });

    this.musicAudio.onpause = () => {
      console.log('单句-播放暂停');
      this.setState({
        playings: [],
      });
    };
    this.musicAudio.onended = () => {
      console.log('单句-播放结束');
      // 播放完，恢复为初始状态
      this.setState({
        playings: [],
      });
    };
  }

  componentDidMount() {
    const { centerCallId } = this.state;
    console.log('chat-seat-mount***', centerCallId);

    // 查询监听id，如果是当前弹屏，需要开启监听样式
    const listenCallId = (this.props as JSONObject).manListenCallId;
    if (centerCallId === listenCallId) {
      console.log('当前监听通话***', listenCallId);
      // 当前id跟监听id相同，则需要自动开启监听样式
      this.openListen();
    }
  }

  /**
   * 频繁比较state和prop是一件比较麻烦的事（由于地址引用，需要转字符串再比较），
   * 考虑到开销将message的更新提取为setRecord方法
   */
  componentDidUpdate(prop: ChatProp): void {
    // console.log("chatSeat组件更新");
    const state = this.state;
    const checkPhone = state.phoneNum === prop.phoneNum;
    const callTime = state.callTime === prop.callTime;
    const checkStatus = state.status === prop.status;
    const checkCallId = state.callRecordId === prop.callRecordId;
    const checkCenterId = state.centerCallId === prop.centerCallId;
    const checkTalkRecord = state.talkRecord === prop.talkRecord;
    if (checkPhone && callTime && checkStatus && checkCallId && checkCenterId && checkTalkRecord) {
      return;
    }
    this.setState(
      {
        phoneNum: prop.phoneNum,
        callTime: prop.callTime,
        status: prop.status,
        callRecordId: prop.callRecordId,
        centerCallId: prop.centerCallId,
        talkRecord: prop.talkRecord,
      },
      () => {
        this.forceUpdate();
      }
    );
  }
  componentWillUnmount() {
    const { centerCallId, isTransferShow } = this.state;
    console.log('chat-seat-unmount', centerCallId);
    // 查询监听id，如果是当前弹屏，需要将缓存弹屏id置空
    const listenCallId = (this.props as JSONObject).manListenCallId;
    if (centerCallId === listenCallId) {
      console.log('监听的通话已挂断', listenCallId);
      (this.props as JSONObject).setManListenCallId('');
    }
    // 1.弹屏消失，需要隐藏【接听】按钮
    if (isTransferShow) {
      console.log('当前显示【接听】按钮,需要隐藏，移除接听事件', centerCallId);
      this.hideTransferPop();
      eventBus.emit('hideTransferPop', centerCallId);
    }

    // 单句播放暂停
    this.musicAudio.pause();
    this.setState = (state, callback) => {
      return;
    };
  }

  /**
   * 置空会话
   */
  public clear(): void {
    this.setState({
      messages: [],
      phoneNum: void 0,
      callTime: '',
    });
  }

  /**坐席-接听 */
  public seatCall(): void {
    getSysSip()
      .waitInit()
      .then(ins => {
        // 123
      });
  }

  /**坐席监听-开启样式 */
  public openListen(): void {
    this.setState({
      inCall: true,
    });
  }
  /**
   * 结束监听：
   */
  public stopListen(): void {
    getSysSip()
      .waitInit()
      .then(ins => {
        // 挂断监听
        ins.stopAudio();
      });
  }

  /**
   * 查询历史
   */
  private fetchHistory = async () => {
    try {
      const res = await getDialogue(
        {
          callRecordId: this.state.callRecordId as string,
          time: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'),
        },
        this.state.chatType
      );
      console.log('查看历史res===', res);
      // 点击查看历史记录时，页面接收到的所有推送消息
      const record = this.state.messages;
      // 完整通话记录：历史记录拼接在推送消息前面
      const msg = res.data
        .map(item => {
          return {
            index: item.index,
            role: item.role === 1 ? 'caller' : 'called',
            message: item.text,
            sound: item.url,
            status: item.status,
          };
        })
        .concat(record as ChatMessage[]);

      // 通话记录拼接后去重
      const newMsg = filterDialogue(msg as ChatMessage[]);
      // 隐藏查看历史按钮，拼接聊天记录上屏展示
      this.setState({
        showHistoryLink: false,
        messages: newMsg as ChatMessage[],
      });
      if (!newMsg.length) {
        // 查看历史获取消息为空，不触发回调
        return;
      }
      // 回调
      this.props.onGetHistory &&
        this.props.onGetHistory(
          newMsg as ChatMessage[],
          this.state.callRecordId as string,
          this.state.callSerialNumber as string
        );
    } catch (error) {
      console.error(`系统异常: ${JSON.stringify(error)}`);
    }
  };

  /**
   * 滚动到最底部
   */
  public scrollToBottom(): void {
    const domContainer = this.bodyRef.current;
    if (!domContainer) {
      return;
    }
    const scrollDistance = domContainer.clientHeight + domContainer.scrollTop;
    const scrollHeight = domContainer.scrollHeight;
    if (scrollDistance > scrollHeight - 20 || scrollDistance < scrollHeight + 20) {
      domContainer.scroll(0, 200000);
    }
  }

  /**
   * 操作【转人工接听】
   */
  public async handleContactMan(): Promise<void> {
    const { callRecordId, centerCallId } = this.state;
    console.group(
      '%c%s',
      'color:orange',
      'handleContactMan->>即将跳转【转人工接听】',
      callRecordId,
      centerCallId
    );
    try {
      const listenCallId = (this.props as JSONObject).manListenCallId;
      if (listenCallId) {
        // 存在正在监听的弹屏
        await closeListenCall(listenCallId as string);
        console.log(listenCallId, '$$$$$$$$$$$$$$$$$$>>>>>>>>接口成功>>>监听通话-关闭');
        eventBus.emit('closeManListenOk', listenCallId);
      }
      this.hideTransferPop();
      this.props.goNext && this.props.goNext(callRecordId, centerCallId, 'robot');
    } catch (error) {
      console.error(`系统异常: ${JSON.stringify(error)}`);
    }
  }

  /**
   * 操作【人工介入-截听通话】
   */
  public async handleInterceptCall(): Promise<void> {
    const { callRecordId, centerCallId } = this.state;
    try {
      const listenCallId = (this.props as JSONObject).manListenCallId;
      if (listenCallId) {
        await closeListenCall(listenCallId as string);
        console.log(listenCallId, '$$$$$$$$$$$$$$$$$$>>>>>>>>接口成功>>>监听通话-关闭');
        eventBus.emit('closeManListenOk', listenCallId);
      }
      await interceptCall(centerCallId as string);
      console.log(centerCallId, '>>>>>>>>接口成功>>>【人工介入】--跳转【人工介入页面】');
      this.props.goNext && this.props.goNext(callRecordId, centerCallId, 'seat');
    } catch (error) {
      console.error(`系统异常: ${JSON.stringify(error)}`);
    }
  }

  /**
   * 操作【人工监听-开启】
   */
  public async handleOpenManListenCall(): Promise<void> {
    const { centerCallId } = this.state;

    try {
      console.group('%c%s', 'color:blue', '$$$$$$$$$$$$$======当前弹屏id=====', centerCallId);
      const listenCallId = (this.props as JSONObject).manListenCallId;
      if (listenCallId) {
        await closeListenCall(listenCallId as string);
        console.log(listenCallId, '$$$$$$$$$$$$$$$$$$>>>>>>>>接口成功>>>监听通话-关闭');
        eventBus.emit('closeManListenOk', listenCallId);
      }
      // 弹屏无监听，再开启
      await openListenCall(centerCallId as string);
      console.log(
        centerCallId,
        '监听id====>>>>>>接口成功>>>监听通话-【开启】>>>====√√√√√√√√√√√√√√√√√√√√√√√√√√√√√√√√√'
      );
      this.openListen();
      (this.props as JSONObject).setManListenCallId(centerCallId as string);
    } catch (error) {
      console.error(`系统异常: ${JSON.stringify(error)}`);
    }
  }
  /**
   * 操作【人工监听-关闭】
   */
  public async handleCloseManListenCall(): Promise<void> {
    const { centerCallId } = this.state;
    try {
      if (centerCallId) {
        const listenCallId = centerCallId;
        await closeListenCall(listenCallId);
        console.log(listenCallId, '$$$$$$$$$$$$$$$$$$接口成功>>>人工监听通话-关闭');
        eventBus.emit('closeManListenOk', listenCallId);
      }
    } catch (error) {
      console.error(`系统异常: ${JSON.stringify(error)}`);
    }
  }
  render() {
    const {
      showHeadBar,
      showStatusHeader,
      phoneNum,
      callTime,
      messages,
      status,
      inCall,
      showHistoryLink,
      talkRecord,
      isTransferShow,
      centerCallId,
      callRecordId,
    } = this.state;
    const { calledImg, callerImg, bodyRef, audioRef, musicAudio } = this;
    const playIconStyle = {
      marginRight: '5px',
      fontSize: '16px',
    };
    const playingIconStyle = {
      marginRight: '5px',
      fontSize: '16px',
    };
    const placeholderIconStyle = {
      fontSize: '75px',
      color: 'red',
    };

    return (
      <>
        <div className="chatseat">
          {showStatusHeader && (
            <div className="chat-status-header">
              <span className="chat-statusheader-phone">
                {webDebug && (
                  <b className="debug-style">
                    【{centerCallId}】[{callRecordId}]
                  </b>
                )}
                {phoneNum}
              </span>
              {callTime && <CallTime beginTime={callTime} />}
            </div>
          )}
          <div className="chat-sound-header">
            {showHeadBar && talkRecord && talkRecord?.indexOf('null') < 0 && (
              <>
                <div className="chat-sound-bar">
                  <WAudio
                    id={talkRecord}
                    ref={audioRef}
                    src={talkRecord as string}
                    outAudio={musicAudio}
                  />
                </div>
                <Button
                  type="link"
                  icon={<VerticalAlignBottomOutlined />}
                  href={talkRecord + '?n=aaa'}
                  // n=aaa为后端定义传参，方便识别为下载文件
                  download
                />
              </>
            )}
          </div>
          <div className="chat-body" ref={bodyRef}>
            {/* status：3-通话中-查看历史 */}
            {showHistoryLink && (status === 2 || status === 3) && (
              <div className="chat-showhistory">
                <Button type="link" onClick={this.fetchHistory}>
                  查看历史
                </Button>
              </div>
            )}
            {/* 历史记录-信息展示 */}
            {messages?.length !== 0 &&
              messages?.map((item, index) => {
                if (item.role === 'caller') {
                  return (
                    <div className="chat-message" key={'caller_' + index}>
                      <span className="chat-message-caller">
                        <img className="chat-ava" src={callerImg} alt="caller" />
                      </span>
                      <span className="chat-message-callermessage">
                        {webDebug && (
                          <>
                            <b className="debug-style">【{callRecordId}】</b>
                            【序号{item.index}】
                          </>
                        )}
                        {item.message}
                      </span>
                    </div>
                  );
                } else if (item.role === 'called') {
                  return (
                    <div
                      className={
                        item.status
                          ? 'chat-message called-message'
                          : 'chat-message called-message chat-message-not-understand'
                      }
                      key={'called_' + index}
                    >
                      <span className="chat-message-calledava">
                        <img className="chat-ava" src={calledImg} alt="called" />
                      </span>
                      <span className="chat-message-calledmessage">
                        <>
                          {!!item.sound && (
                            <>
                              {this.state.playings[index] ? (
                                <AudioOutlined style={playingIconStyle} />
                              ) : (
                                <AudioFilled
                                  style={playIconStyle}
                                  onClick={() => {
                                    this.playSound(item, index);
                                  }}
                                />
                              )}
                            </>
                          )}
                          {webDebug && (
                            <>
                              <b className="debug-style">【{callRecordId}】</b>
                              【序号{item.index}】
                            </>
                          )}
                          {item.message}
                        </>
                      </span>
                      {item.status === 0 && <span className="messaget-tip">未理解</span>}
                    </div>
                  );
                } else {
                  return (
                    <div key={'caller_' + index} className="chat-transferman">
                      {webDebug && (
                        <>
                          <b className="debug-style">【{callRecordId}】</b>
                          【序号{item.index}】
                        </>
                      )}
                      {item.message}
                    </div>
                  );
                }
              })}
            {messages?.length === 0 && status !== 1 && <Empty description={<span>无记录</span>} />}
            {/* status-呼叫中，响铃 */}
            {status === 1 && (
              <div className="chat-incall-placeholder">
                <PhoneOutlined style={placeholderIconStyle} />
              </div>
            )}
          </div>
          {/* 当流程触发转人工组件节点，显示转人工接听-提示框 */}
          <div className="chat-foot">
            {/*转人工接听按钮*/}
            <div className={`man-message ${isTransferShow ? 'message-pop-in' : ''}`}>
              <Space size="large" align="center" className="man-message-box">
                <div className="box-left">
                  <b>客户需要转人工</b>
                  <span className="blue">等待时长：{(this.waitTimeRef as any).current}秒</span>
                </div>
                <Button
                  className="btn-circle"
                  type="primary"
                  shape="circle"
                  size="large"
                  icon={<PhoneOutlined />}
                  onClick={() => {
                    console.log('&&&&&&&&&&&手动接听*****', centerCallId);
                    this.handleContactMan();
                  }}
                >
                  <span className="text">接听</span>
                </Button>
              </Space>
            </div>
            {/* 按钮区块 */}
            <Space size="large" align="center">
              <Button
                className="btn-circle"
                type="primary"
                shape="circle"
                size="large"
                icon={<CustomerServiceOutlined />}
                onClick={this.handleInterceptCall}
              >
                <span className="text">人工介入</span>
              </Button>
              <Button
                className={inCall ? 'btn-circle ' : 'btn-circle btn-shake'}
                type="primary"
                danger={inCall ? true : false}
                ghost
                shape="circle"
                size="large"
                icon={<SoundOutlined />}
                onClick={inCall ? this.handleCloseManListenCall : this.handleOpenManListenCall}
              >
                <span className="text">人工监听</span>
              </Button>
            </Space>
          </div>
        </div>
      </>
    );
  }
}

// state 注入props
const mapStateToProps = (state: JSONObject) => {
  return {
    manListenCallId: state.manListenCallId,
  };
};
// action 注入props
const mapDispatchToProps = {
  setManListenCallId,
};

export default connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })(ChatSeat);

// 测试用例
export const ChatCollectTest: React.FC = () => {
  const initValue = [
    {
      role: 'caller',
      message: '试试运用自如！',
    },
    {
      role: 'called',
      message: 'wow awsome!',
    },
    {
      role: 'man',
      message: '2020/12/01 转人工至aa',
    },
  ] as ChatMessage[];

  return (
    <>
      <ChatSeat messages={initValue} showStatusHeader={false} />
    </>
  );
};
